#!/usr/bin/perl -w

BEGIN   
{
	sub getPoints{return '../../' if (!$_[1]);return '../' if (!$_[0]);return '/';}
	(my $file = __FILE__) =~ s/\/?(modules\/)?(nf_conntrack\/)?(\w+\.pl)$/&getPoints($1,$2)/e;
	$file = './' if $file eq '/';
	unshift(@INC, $file."bin");
}

use strict;
use Socket;
use TWM;

my $dnsresolution = 1;
my $portresolution = 1;
my $masqueradeonly = 0;
my $establishedonly = 0;
my $directonly = 0;
my $showheader = 1;
my $host = 0;
my $ip_src = '\S+';
my $ip_dst = '\S+';
my $port_src = '\d+';
my $port_dst = '\d+';
my $web = 0;
my $subtitle = "";
my $ip_conntrack = $cm{proc_net_ip_conntrack};
my %ports;
$| = 1;


for (my $i=0; $i<=$#ARGV; $i++)	{
	$_ = $ARGV[$i];
	if (/\-\-src/)	{
		$i++;
		$ip_src = $1 if ($ARGV[$i] =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/);
		next;
	}
	if (/\-\-dst/)	{
		$i++;
		$ip_dst = $1 if ($ARGV[$i] =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/);
		next;
	}
	if (/\-\-host/)	{
		$i++;
		$host = 1;
		$ip_src = $1 if ($ARGV[$i] =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/);
		$ip_dst = $ip_src;
		next;
	}
	if (/\-\-port_src/)	{
		$i++;
		$port_src = $1 if ($ARGV[$i] =~ /(\d+)/);
		next;
	}
	if (/\-\-port_dst/)	{
		$i++;
		$port_dst = $1 if ($ARGV[$i] =~ /(\d+)/);
		next;
	}
	$dnsresolution = 0 if (/\-\w*n/);
	$portresolution = 0 if (/\-\w*p/);
	$showheader = 0 if (/\-\w*t/);
	$establishedonly = 1 if (/\-\w*e/);
	$web = 1 if (/\-\w*w/);
	if (/\-\w*m/)	{
		$masqueradeonly = 1;
		$subtitle = 'MASQUERADED';
	}
	if (/\-\w*d/)	{
		$directonly = 1;
		$subtitle = 'DIRECT';
	}
	if (/\-\w*h/)	{
		print "USAGE: perl ".__FILE__." [options]\n";
		print "Options:\n";
		print "  -n           No dns resolution (this is faster)\n";
		print "  -p           No port resolution (this is faster)\n";
		print "  -e           Established connections only\n";
		print "  -m           Masqueraded connections only\n";
		print "  -d           Direct connections only\n";
		print "  --host       Results for specified ip\n";
		print "  --src        Results for specified source ip\n";
		print "  --dst        Results for specified destination ip\n";
		print "  --port_src   Results for specified source port\n";
		print "  --port_dst   Results for specified destination port\n";
		print "  -t           Results only, hide header\n";
		print "  -w           Results with TAB delimiter to simple parse web script\n";
		print "  -h           Print this help\n";
		exit 1;
	} 
}
my $titre = "Active $subtitle Connections according to $ip_conntrack";


open(ICT, $ip_conntrack) || die("Can not open ip_conntrack: $!");
my @ip_conntrack_brut = <ICT>;
close(ICT);
#print @ip_conntrack_brut;

if ($showheader)	{
	print "$titre\n";
	print formatedData($web, "Proto", 10).formatedData($web, "Source Address", 25).formatedData($web, "Remote Address", 25).formatedData($web, "Service", 25).formatedData($web, "State", 15);
	((!$masqueradeonly && !$directonly) || $web) && print formatedData($web, "Masq", 8);
	($dnsresolution || $web) && print "Name Resolution";
	print "\n";
}

my $est_str = $establishedonly?'ESTABLISHED':'\w+';
foreach (@ip_conntrack_brut)	{
	s/\[\S+\]\s//;
	my ($proto, $state, $srcaddr, $dstaddr, $srcport, $dstport, $plpl, $srcportname, $dstportname, $portname, $topackets, $tobytes, $frompackets, $frombytes) = ("")x14;
	if ( 
		(
			!$host
			&&
			/ipv4\s+\d+\s+(tcp)\s+(\d+)\s+(\d+)\s+($est_str)\s+src=($ip_src)\s+dst=($ip_dst)\s+sport=($port_src)\sdport=($port_dst)\spackets=(\d+)\sbytes=(\d+)\ssrc=(\S+)\sdst=(\S+)\ssport=(\d+)\sdport=(\d+)\spackets=(\d+)\sbytes=(\d+)\s.*/
		)
		|| 
		(
			$host
			&&
			(
				/ipv4\s+\d+\s+(tcp)\s+(\d+)\s+(\d+)\s+($est_str)\s+src=($ip_src)\s+dst=(\S+)\s+sport=($port_src)\sdport=($port_dst)\spackets=(\d+)\sbytes=(\d+)\ssrc=(\S+)\sdst=(\S+)\ssport=(\d+)\sdport=(\d+)\spackets=(\d+)\sbytes=(\d+)\s.*/
				||
				/ipv4\s+\d+\s+(tcp)\s+(\d+)\s+(\d+)\s+($est_str)\s+src=(\S+)\s+dst=($ip_dst)\s+sport=($port_src)\sdport=($port_dst)\spackets=(\d+)\sbytes=(\d+)\ssrc=(\S+)\sdst=(\S+)\ssport=(\d+)\sdport=(\d+)\spackets=(\d+)\sbytes=(\d+)\s.*/
			)
		)
	)	{
		($proto, $state, $srcaddr, $dstaddr, $srcport, $dstport, $topackets, $tobytes, $plpl, $frompackets, $frombytes) = ($1, $4, $5, $6, $7, $8, $9, $10, $11, $15, $16);
	} elsif ( 
		(
			!$host 
			&& 
			/ipv4\s+\d+\s+(udp)\s+(\d+)\s+(\d+)\s+src=($ip_src)\s+dst=($ip_dst)\s+sport=($port_src)\s+dport=($port_dst)\s+packets=(\d+)\sbytes=(\d+)\s+src=(\S+)\s+dst=(\S+)\ssport=(\d+)\s+dport=(\d+)\s+packets=(\d+)\sbytes=(\d+)\s.*/
		) 
		||
		(
			$host 
			&& 
			(
				/ipv4\s+\d+\s+(udp)\s+(\d+)\s+(\d+)\s+src=($ip_src)\s+dst=(\S+)\s+sport=($port_src)\s+dport=($port_dst)\s+packets=(\d+)\sbytes=(\d+)\s+src=(\S+)\s+dst=(\S+)\ssport=(\d+)\s+dport=(\d+)\s+packets=(\d+)\sbytes=(\d+)\s.*/
				||
				/ipv4\s+\d+\s+(udp)\s+(\d+)\s+(\d+)\s+src=(\S+)\s+dst=($ip_dst)\s+sport=($port_src)\s+dport=($port_dst)\s+packets=(\d+)\sbytes=(\d+)\s+src=(\S+)\s+dst=(\S+)\ssport=(\d+)\s+dport=(\d+)\s+packets=(\d+)\sbytes=(\d+)\s.*/
		)) )	{
		($proto, $srcaddr, $dstaddr, $srcport, $dstport, $topackets, $tobytes, $plpl, $frompackets, $frombytes) = ($1, $4, $5, $6, $7, $8, $9, $10, $14, $15);
	}else	{
		next;
#		toErrorLog("__FILE__. undefined packet: $_");
	}

	if ($portresolution)	{
		if (exists($ports{"$srcport, $proto"}))	{
			$srcportname = $ports{"$srcport, $proto"};
		}else	{
			$srcportname = getservbyport($srcport,$proto) || " ";
			$ports{"$srcport, $proto"} = $srcportname;
		}
		if (exists($ports{"$dstport, $proto"}))	{
			$dstportname = $ports{"$dstport, $proto"};
		}else	{
			$dstportname = getservbyport($dstport,$proto) || " ";
			$ports{"$dstport, $proto"} = $dstportname;
		}
		if (!$srcportname && !$dstportname)	{
			$portname = "[???]";
		}else	{
			$portname = "$srcportname > $dstportname";
		}
	}

	if (
		(
			$masqueradeonly
			&& 
			($srcaddr ne $plpl)
		) 
		|| 
		(!$masqueradeonly && !$directonly)
	)	{
		print formatedData($web, $proto, 10).formatedData($web, "$srcaddr:$srcport", 25).formatedData($web, "$dstaddr:$dstport", 25);
		($portresolution || $web) && print formatedData($web, $portname, 25);
		(!$establishedonly || $web) && print formatedData($web, $state, 15);
		if ((!$masqueradeonly && !$directonly) || $web)	{
			print formatedData($web, ${\(($srcaddr ne $plpl)?"M":"")}, 8);
		}

		if ($dnsresolution)	{
			my $srcname = gethostbyaddr(inet_aton($srcaddr),AF_INET) || "UNRESOLVED";
         	my $dstname = gethostbyaddr(inet_aton($dstaddr),AF_INET) || "UNRESOLVED";
			print formatedData($web, "$srcname > $dstname", 50);
		}elsif ($web)	{
			print formatedData($web, "", 50);
		}
		print formatedData($web, "$tobytes ($topackets)", 20);
		print formatedData($web, "$frombytes ($frompackets)", 20);
		print "\n";
	}elsif ($directonly && ($srcaddr eq $plpl))	{
		print formatedData($web, $proto, 10).formatedData($web, "$srcaddr:$srcport", 25).formatedData($web, "$dstaddr:$dstport", 25);
		($portresolution || $web) && print formatedData($web, $portname, 25);
		(!$establishedonly || $web) && print formatedData($web, $state, 15);
		if ($dnsresolution)	{
			my $srcname = gethostbyaddr(inet_aton($srcaddr),AF_INET) || "UNRESOLVED";
         	my $dstname = gethostbyaddr(inet_aton($dstaddr),AF_INET) || "UNRESOLVED";
			print formatedData($web, "$srcname > $dstname", 50);
		}elsif ($web)	{
			print formatedData($web, "", 50);
		}
		print formatedData($web, "$tobytes ($topackets)", 20);
		print formatedData($web, "$frombytes ($frompackets)", 20);
		print "\n";
	}
}



sub formatedData	{
	if ($_[0])	{
		return ($_[1] || " ")."\t";
	}
	sprintf("%-$_[2]s","$_[1]");
}

__END__

